package com.wing.system.service;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wing.system.dao.DingTalkAttendanceBanDao;
import com.wing.system.dao.DingTalkAttendanceBanRestDao;
import com.wing.system.dao.DingTalkAttendanceBanWorkDao;
import com.wing.system.dao.DingTalkAttendanceDao;
import com.wing.system.model.entity.DingTalkAttendance;
import com.wing.system.model.entity.DingTalkAttendanceBan;
import com.wing.system.model.entity.DingTalkAttendanceBanRest;
import com.wing.system.model.entity.DingTalkAttendanceBanWork;
import com.wing.system.model.response.DingTalkAttendanceVO;
import com.wing.user.feign.UserClient;
import com.wing.user.model.request.SystemDingTalkInfo;
import com.wing.user.model.request.User;
import com.wing.utils.DingDingUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 *
 * @author
 */
@Service
@Slf4j
public class DingTalkAttendanceServiceImpl extends ServiceImpl<DingTalkAttendanceDao, DingTalkAttendance> implements DingTalkAttendanceService {

    @Autowired
    UserClient userClient;

    /**
     * 同步钉钉相关考勤班次情况列表信息
     */
    @Override
    public void syncDingAttendanceToSystem(String beginTime,String endTime) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long beginTimeStr = sdf.parse(beginTime+" 00:00:00").getTime();
        long endTimeStr = sdf.parse(endTime+" 23:59:59").getTime();

        if (endTimeStr <= beginTimeStr) {
            throw new IllegalArgumentException("结束日期必须大于开始日期");
        }

        //获取钉钉后台配置相关
        SystemDingTalkInfo systemDingTalkInfo = userClient.getUserDingConfigInfo();
        if(systemDingTalkInfo!=null){
            //获取钉钉后台accessToken
            String accessToken = DingDingUtils.getAccessTokenByKeySecret(systemDingTalkInfo.getClientId(), systemDingTalkInfo.getClientSecret());
            //获取操作钉钉后台的 管理人员 user_id 信息
            String userManagerId = DingDingUtils.getUserManagerInfoOne(accessToken);
            //获取数据库中保存的 钉钉用户信息
            List<User> userList= userClient.selUserDingInfo();
            //获取钉钉后台人员信息  单次最大50  把user_id ，拼接起来 一次50个，多次就另外一个50个

            if (userList.isEmpty()) {
                System.out.println("No users found in the database.");
                return;
            }

            // 从数据库中的用户列表中提取userid
            List<String> userIds = userList.stream()
                    .map(User::getDingUserId)
                    .collect(Collectors.toList());

            //将相关用户的考勤信息 根据对应日期 和 userIds 先删除掉
            baseMapper.deleteByDateRange(beginTime+" 00:00:00", endTime+" 23:59:59",userIds);


            // 钉钉API单次最大支持的用户数
            final int BATCH_SIZE = 50;

            // 分批处理用户ID
            for (int i = 0; i < userIds.size(); i += BATCH_SIZE) {
                // 计算当前批次的结束索引
                int end = Math.min(i + BATCH_SIZE, userIds.size());
                // 获取当前批次的userIds
                List<String> batchUserIds = userIds.subList(i, end);

                // 将当前批次的user_id拼接成逗号分隔的字符串
                String userIdStr = String.join(",", batchUserIds);


                //根据输入的开始时间和结束时间，批量生成对应的时间戳集合
                List<long[]> timeIntervals = generateWeeklyTimestamps(beginTime, endTime);
                for (long[] interval : timeIntervals) {
                    System.out.println("Start: " + interval[0] + ", End: " + interval[1]);
                    //根据对应参数  批量获取用户考勤信息
                    String userPaiBanInfo = DingDingUtils.getUserPaiBanInfo(accessToken, interval[0], interval[1], userManagerId, userIdStr);
                    JSONObject jsonObject = com.alibaba.fastjson.JSON.parseObject(userPaiBanInfo);
                    if(jsonObject.containsKey("result")){
                        JSONArray resultArray = jsonObject.getJSONArray("result");
                        for (int j = 0; j < resultArray.size(); j++) {
                            JSONObject record = resultArray.getJSONObject(j);
                            DingTalkAttendance dingTalkAttendance = new DingTalkAttendance();
                            if(record.containsKey("check_type")){
                                dingTalkAttendance.setCheckType(record.getString("check_type"));
                            }
                            if(record.containsKey("plan_check_time")){
                                dingTalkAttendance.setPlanCheckTime(record.getString("plan_check_time"));
                            }
                            if(record.containsKey("group_id")){
                                dingTalkAttendance.setGroupId(Long.valueOf(record.getString("group_id")));
                                String groupInfo = DingDingUtils.getAttendanceDetailInfo(DingDingUtils.getAccessToken(),dingTalkAttendance.getGroupId(),userManagerId);
                                ObjectMapper objectMapper = new ObjectMapper();
                                try {
                                    JsonNode rootNode = objectMapper.readTree(groupInfo);
                                     // 检查 "result" 节点是否存在
                                    if (rootNode.has("result") && !rootNode.path("result").isMissingNode()) {
                                        JsonNode resultNode = rootNode.path("result");
                                        // 检查 "name" 节点是否存在
                                        if (resultNode.has("name") && !resultNode.path("name").isMissingNode()) {
                                            String name = resultNode.path("name").asText();
                                            dingTalkAttendance.setGroupName(name);
                                        }
                                    }
                                } catch (Exception e) {
                                    log.error("获取考勤组名称失败", e);
                                }
                            }
                            if(record.containsKey("id")){
                                dingTalkAttendance.setWorkPaiBanId(Long.valueOf(record.getString("id")));
                            }
                            if(record.containsKey("is_rest")){
                                dingTalkAttendance.setIsRest(record.getString("is_rest"));
                            }
                            if(record.containsKey("shift_id")){
                                dingTalkAttendance.setShiftId(Long.valueOf(record.getString("shift_id")));
                            }
                            if(record.containsKey("shift_version")){
                                dingTalkAttendance.setShiftVersion(record.getString("shift_version"));
                            }
                            if(record.containsKey("userid")){
                                dingTalkAttendance.setUserid(record.getString("userid"));
                                String nickname = null;
                                for (User user : userList) {
                                    if (dingTalkAttendance.getUserid().equals(user.getDingUserId())) {
                                        nickname = user.getNickname();
                                        break;
                                    }

                                }
                                dingTalkAttendance.setName(nickname);
                            }
                            if(record.containsKey("work_date")){
                                dingTalkAttendance.setWorkDate(record.getString("work_date"));
                            }
                          /*  String operateUser = null;
                            for (User user : userList) {
                                if (userManagerId.equals(user.getDingUserId())) {
                                    operateUser = user.getNickname();
                                    break;
                                }
                            }
                            //排班人
                            dingTalkAttendance.setOperateUserId(userManagerId);
                            dingTalkAttendance.setOperateUser(operateUser);*/


                            //获取班次基础信息  填充到当前表
                            String banCiListInfo = DingDingUtils.getUserHistoryBanCiInfo(accessToken, dingTalkAttendance.getShiftId(), dingTalkAttendance.getShiftVersion(), userManagerId);
                            ObjectMapper objectMapper = new ObjectMapper();
                            try {
                                JsonNode rootNode = objectMapper.readTree(banCiListInfo);
                                // 检查 "result" 节点是否存在
                                if (rootNode.has("result") && !rootNode.path("result").isMissingNode()) {
                                    JsonNode resultNode = rootNode.path("result");
                                    // 检查 "name" 节点是否存在
                                    if (resultNode.has("name") && !resultNode.path("name").isMissingNode()) {
                                        String banCiName = resultNode.path("name").asText();
                                        dingTalkAttendance.setShiftName(banCiName);
                                    }

                                    //处理班次信息
                                    dealWithAttendanceBanCiData(banCiListInfo);

                                }





                            } catch (Exception e) {
                                // 记录错误信息以及异常堆栈跟踪
                                log.error("获取排班信息有误", e);
                            }

                            // 定义输入日期格式
                            SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            // 定义输出日期格式
                            SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM");

                            try {
                                // 解析输入的日期字符串到Date对象
                                Date date = inputFormat.parse(dingTalkAttendance.getWorkDate());
                                // 使用输出格式格式化Date对象
                                String formattedDate = outputFormat.format(date);
                                //排班月份
                                dingTalkAttendance.setPaiBanMouth(formattedDate);
                            } catch (ParseException e) {
                                // 记录错误信息以及异常堆栈跟踪
                                log.error("日期转换有误", e);
                            }

                            baseMapper.insert(dingTalkAttendance);

                        }
                    }
                }
           }
        }
    }

    @Override
    public Page<DingTalkAttendanceVO> selDingTalkAttendanceInfo(Page<DingTalkAttendanceVO> pg, Map map) {
        List<DingTalkAttendanceVO> vos = baseMapper.selDingTalkAttendanceInfo(pg, map);
        pg.setRecords(vos);
        return pg;
    }

    @Override
    public void syncDingAttendanceBanCiSystem() throws Exception {
        //获取钉钉后台配置相关
        SystemDingTalkInfo systemDingTalkInfo = userClient.getUserDingConfigInfo();
        if(systemDingTalkInfo!=null){
            String accessToken = DingDingUtils.getAccessTokenByKeySecret(systemDingTalkInfo.getClientId(), systemDingTalkInfo.getClientSecret());
            //获取操作钉钉后台的 管理人员 user_id 信息
            String userManagerId = DingDingUtils.getUserManagerInfoOne(accessToken);
            String userPaiBanInfo = DingDingUtils.getAttendanceShiftInfo(accessToken, null, userManagerId);

            JSONObject jsonObject = JSON.parseObject(userPaiBanInfo);
            JSONObject outerResult = jsonObject.getJSONObject("result");
            // 获取内层result数组
            JSONArray innerResults = outerResult.getJSONArray("result");
            for (int j = 0; j < innerResults.size(); j++) {
                JSONObject record = innerResults.getJSONObject(j);
                if(record.containsKey("id")){
                    //同步班次考勤相关信息
                    String attendanceShiftDetailInfo = DingDingUtils.getAttendanceShiftDetailInfo(DingDingUtils.getAccessToken(), record.getString("id"), userManagerId);
                    dealWithAttendanceBanCiData(attendanceShiftDetailInfo);
                }
             }
         }
    }

    @Override
    public Page<DingTalkAttendanceVO> selDingTalkAttendancePaiBanInfo(Page<DingTalkAttendanceVO> pg, Map map) {
        List<DingTalkAttendanceVO> vos = baseMapper.selDingTalkAttendancePaiBanInfo(pg, map);
        pg.setRecords(vos);
        return pg;
    }


    public static void main(String[] args) throws Exception {
        String beginTime = "2024-03-01 00:00:00";
        String endTime = "2024-03-31 23:59:59";

        List<long[]> timeIntervals = generateWeeklyTimestamps(beginTime, endTime);
        for (long[] interval : timeIntervals) {
            System.out.println("Start: " + interval[0] + ", End: " + interval[1]);
        }
    }

    /**
     * 根据开始时间和结束时间生成每七天的时间区间（毫秒时间戳）
     */
    public static List<long[]> generateWeeklyTimestamps(String beginTimeStr, String endTimeStr) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long startTime = sdf.parse(beginTimeStr+" 00:00:00").getTime();
        long endTime = sdf.parse(endTimeStr+" 23:59:59").getTime();
        if (endTime <= startTime) {
            throw new IllegalArgumentException("结束日期必须大于开始日期");
        }

        List<long[]> intervals = new ArrayList<>();
        long currentStart = startTime;
        while (currentStart < endTime) {
            long currentEnd = Math.min(currentStart + 7L * 24 * 60 * 60 * 1000 - 1, endTime);
            intervals.add(new long[]{currentStart, currentEnd});
            currentStart += 7L * 24 * 60 * 60 * 1000; // Move to the next week
        }

        return intervals;
    }



    @Autowired
    private DingTalkAttendanceBanDao dingTalkAttendanceBanDao;

    @Autowired
    private DingTalkAttendanceBanRestDao dingTalkAttendanceBanRestDao;

    @Autowired
    private DingTalkAttendanceBanWorkDao dingTalkAttendanceBanWorkDao;


    /**
     * 处理班次信息
     * @throws Exception
     */
    public void dealWithAttendanceBanCiData(String banCiJsonInfo) throws Exception {
        JSONObject jsonObject = com.alibaba.fastjson.JSON.parseObject(banCiJsonInfo);
        JSONObject resultObject = jsonObject.getJSONObject("result");
        JSONObject shiftSettingObject = resultObject.getJSONObject("shift_setting");

        DingTalkAttendanceBan dingTalkAttendanceBan = new DingTalkAttendanceBan();

        // 设置 DingTalkAttendanceBan 的属性，使用 containsKey 进行安全检查
        if (resultObject.containsKey("corp_id")) {
            dingTalkAttendanceBan.setCorpId(resultObject.getString("corp_id"));
        }
        if (resultObject.containsKey("name")) {
            dingTalkAttendanceBan.setBanName(resultObject.getString("name"));
        }
        if (resultObject.containsKey("id")) {
            String banId = resultObject.getString("id");
            dingTalkAttendanceBan.setBanId(Long.valueOf(banId));
        }
        if (resultObject.containsKey("shift_group_name")) {
            dingTalkAttendanceBan.setShiftGroupName(resultObject.getString("shift_group_name"));
        }
        if (resultObject.containsKey("shift_group_id")) {
            dingTalkAttendanceBan.setShiftGroupId(resultObject.getString("shift_group_id"));
        }

        if (shiftSettingObject.containsKey("shift_id")) {
            dingTalkAttendanceBan.setShiftId(Long.valueOf(shiftSettingObject.getString("shift_id")));
        }
        if (shiftSettingObject.containsKey("gmt_modified")) {
            dingTalkAttendanceBan.setGmtModified(shiftSettingObject.getString("gmt_modified"));
        }
        if (shiftSettingObject.containsKey("is_deleted")) {
            dingTalkAttendanceBan.setDingIsDeleted(shiftSettingObject.getString("is_deleted"));
        }
        if (shiftSettingObject.containsKey("work_time_minutes")) {
            dingTalkAttendanceBan.setWorkTimeMinutes(Integer.valueOf(shiftSettingObject.getString("work_time_minutes")));
        }
        if (shiftSettingObject.containsKey("attend_days")) {
            dingTalkAttendanceBan.setAttendDays(shiftSettingObject.getString("attend_days"));
        }
        if (shiftSettingObject.containsKey("gmt_create")) {
            dingTalkAttendanceBan.setGmtCreate(shiftSettingObject.getString("gmt_create"));
        }

        // 删除旧记录
        QueryWrapper<DingTalkAttendanceBan> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ban_id", dingTalkAttendanceBan.getBanId());
        dingTalkAttendanceBanDao.delete(queryWrapper);

        // 插入新记录
        dingTalkAttendanceBanDao.insert(dingTalkAttendanceBan);

        JSONArray sectionsArray = resultObject.getJSONArray("sections");
        for (int i = 0; i < sectionsArray.size(); i++) {
            JSONObject sectionObject = sectionsArray.getJSONObject(i);

            // 处理 rests
            if (sectionObject.containsKey("rests")) {
                JSONArray restsArray = sectionObject.getJSONArray("rests");

                if(restsArray.size()>0){
                    // 删除旧记录
                    QueryWrapper<DingTalkAttendanceBanRest> queryWrapper2 = new QueryWrapper<>();
                    queryWrapper2.eq("ban_id", dingTalkAttendanceBan.getBanId());
                    dingTalkAttendanceBanRestDao.delete(queryWrapper2);
                }


                for (int j = 0; j < restsArray.size(); j++) {
                    JSONObject restObject = restsArray.getJSONObject(j);
                    DingTalkAttendanceBanRest dingTalkAttendanceBanRest = new DingTalkAttendanceBanRest();

                    if (restObject.containsKey("across")) {
                        dingTalkAttendanceBanRest.setAcross(Integer.valueOf(restObject.getString("across")));
                    }
                    if (restObject.containsKey("check_time")) {
                        dingTalkAttendanceBanRest.setCheckTime(restObject.getString("check_time"));
                    }
                    if (restObject.containsKey("check_type")) {
                        dingTalkAttendanceBanRest.setCheckType(restObject.getString("check_type"));
                    }
                    if (restObject.containsKey("id")) {
                        dingTalkAttendanceBanRest.setRestId(Integer.valueOf(restObject.getString("id")));
                    }

                    dingTalkAttendanceBanRest.setBanId(dingTalkAttendanceBan.getBanId());
                    dingTalkAttendanceBanRest.setBanName(dingTalkAttendanceBan.getBanName());
                    dingTalkAttendanceBanRest.setBanKeyId(dingTalkAttendanceBan.getId());



                    // 插入新记录
                    dingTalkAttendanceBanRestDao.insert(dingTalkAttendanceBanRest);
                }
            }

            // 处理 punches
            if (sectionObject.containsKey("punches")) {
                JSONArray punchesArray = sectionObject.getJSONArray("punches");

                if(punchesArray.size()>0){
                    // 删除旧记录
                    QueryWrapper<DingTalkAttendanceBanWork> queryWrapper3 = new QueryWrapper<>();
                    queryWrapper3.eq("ban_id", dingTalkAttendanceBan.getBanId());
                    dingTalkAttendanceBanWorkDao.delete(queryWrapper3);
                }

                for (int k = 0; k < punchesArray.size(); k++) {
                    JSONObject punchObject = punchesArray.getJSONObject(k);
                    DingTalkAttendanceBanWork dingTalkAttendanceBanWork = new DingTalkAttendanceBanWork();

                    if (punchObject.containsKey("across")) {
                        dingTalkAttendanceBanWork.setAcross(Integer.valueOf(punchObject.getString("across")));
                    }
                    if (punchObject.containsKey("begin_min")) {
                        dingTalkAttendanceBanWork.setBeginMin(punchObject.getString("begin_min"));
                    }
                    if (punchObject.containsKey("check_time")) {
                        dingTalkAttendanceBanWork.setCheckTime(punchObject.getString("check_time"));
                    }
                    if (punchObject.containsKey("check_type")) {
                        dingTalkAttendanceBanWork.setCheckType(punchObject.getString("check_type"));
                    }
                    if (punchObject.containsKey("end_min")) {
                        dingTalkAttendanceBanWork.setEndMin(punchObject.getString("end_min"));
                    }
                    if (punchObject.containsKey("free_check")) {
                        dingTalkAttendanceBanWork.setFreeCheck(punchObject.getString("free_check"));
                    }
                    if (punchObject.containsKey("permit_minutes")) {
                        dingTalkAttendanceBanWork.setPermitMinutes(punchObject.getString("permit_minutes"));
                    }

                    dingTalkAttendanceBanWork.setBanId(dingTalkAttendanceBan.getBanId());
                    dingTalkAttendanceBanWork.setBanName(dingTalkAttendanceBan.getBanName());
                    dingTalkAttendanceBanWork.setBanKeyId(dingTalkAttendanceBan.getId());

                    // 插入新记录
                    dingTalkAttendanceBanWorkDao.insert(dingTalkAttendanceBanWork);
                }
            }
        }
    }


}
